参考博客:http://blog.csdn.net/u014135021/article/details/50995386
汉诺塔的递推核心代码为
a[1]=1;
for(int i=2;i<=n;i++)
a[i]=2*a[I-1]+1;
由递归算法可知,我们要想把A塔上n个盘子挪到C盘
1先把n-1个盘子挪到B盘
2把第n个盘子挪到C盘
3n-1个盘子挪到c盘
1和3步骤近似相同,只是借助的塔不一样。我们不妨开一个数组a,a[I]表示移动I个盘子所需要步数,我们可知第一步对应的步数为a[n-1],所以得到上面的递推公式
汉诺塔IX
HDU - 2175
1,2,...,n表示n个盘子.数字大盘子就大.n个盘子放在第1根柱子上.大盘不能放在小盘上.
在第1根柱子上的盘子是a[1],a[2],...,a[n]. a[1]=n,a[2]=n-1,...,a[n]=1.即a[1]是最下
面的盘子.把n个盘子移动到第3根柱子.每次只能移动1个盘子,且大盘不能放在小盘上.
问第m次移动的是那一个盘子.
Input
每行2个整数n (1 ≤ n ≤ 63) ,m≤ 2^n-1.n=m=0退出
Output
输出第m次移动的盘子的号数.
Sample Input
63 1
63 2
0 0
1 2
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; long long n, m; long long a[65], b[65]; void init() { a[1] = 1; b[1] = 2; b[0] = 1; for(int i = 2; i <= 63; i ++) { a[i] = a[i - 1]*2 + 1; b[i] = a[i] + 1; } } int sove() { if(m == a[63]) return 1; while(m > 0) { int t = 0; while(m > b[t]) { t ++; } if(m == b[t]) return t + 1; m -= b[t - 1]; } } int main() { init(); while(scanf("%lld %lld", &n, &m) != EOF) { if(n == 0&&m == 0) break; printf("%d\n", sove()); } return 0; }